فارسی

قدرت الگوی Render Props در React را کشف کنید. بیاموزید چگونه این الگو استفاده مجدد از کد، ترکیب‌بندی کامپوننت و جداسازی دغدغه‌ها را ترویج می‌دهد و برنامه‌های انعطاف‌پذیر و قابل نگهداری برای مخاطبان بین‌المللی ایجاد می‌کند.

الگوی Render Props در React: منطق کامپوننت انعطاف‌پذیر برای مخاطبان جهانی

در چشم‌انداز همواره در حال تحول توسعه فرانت‌اند، به‌ویژه در اکوسیستم React، الگوهای معماری نقشی حیاتی در ساخت کامپوننت‌های مقیاس‌پذیر، قابل نگهداری و قابل استفاده مجدد ایفا می‌کنند. در میان این الگوها، الگوی Render Props به عنوان یک تکنیک قدرتمند برای به اشتراک‌گذاری کد و منطق بین کامپوننت‌های React برجسته است. این پست وبلاگ با هدف ارائه درک جامعی از الگوی Render Props، مزایا، موارد استفاده و چگونگی کمک آن به ساخت برنامه‌های قوی و سازگار برای مخاطبان جهانی نوشته شده است.

Render Props چیست؟

یک Render Prop تکنیک ساده‌ای برای به اشتراک‌گذاری کد بین کامپوننت‌های React با استفاده از یک prop است که مقدار آن یک تابع است. در اصل، یک کامپوننت با یک render prop تابعی را می‌گیرد که یک عنصر React را برمی‌گرداند و این تابع را برای رندر کردن چیزی فراخوانی می‌کند. کامپوننت مستقیماً تصمیم نمی‌گیرد چه چیزی را رندر کند؛ بلکه این تصمیم را به تابع render prop واگذار می‌کند و به آن امکان دسترسی به وضعیت و منطق داخلی خود را می‌دهد.

این مثال ساده را در نظر بگیرید:


class DataProvider extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null };
  }

  componentDidMount() {
    // Simulate fetching data
    setTimeout(() => {
      this.setState({ data: 'Some data from an API' });
    }, 1000);
  }

  render() {
    return this.props.render(this.state.data);
  }
}

function MyComponent() {
  return (
     (
        
{data ?

Data: {data}

:

Loading...

}
)} /> ); }

در این مثال، DataProvider داده‌ها را دریافت کرده و آن را به تابع prop render که توسط MyComponent ارائه شده است، پاس می‌دهد. سپس MyComponent از این داده‌ها برای رندر کردن محتوای خود استفاده می‌کند.

چرا از Render Props استفاده کنیم؟

الگوی Render Props چندین مزیت کلیدی ارائه می‌دهد:

موارد استفاده در دنیای واقعی و مثال‌های بین‌المللی

الگوی Render Props در سناریوهای مختلفی ارزشمند است. در اینجا برخی از موارد استفاده رایج با مثال‌هایی که مخاطبان جهانی را در نظر می‌گیرند، آورده شده است:

۱. ردیابی ماوس

تصور کنید می‌خواهید موقعیت ماوس را در یک صفحه وب ردیابی کنید. با استفاده از یک Render Prop، می‌توانید یک کامپوننت MouseTracker ایجاد کنید که مختصات ماوس را به فرزندان خود ارائه می‌دهد.


class MouseTracker extends React.Component {
  constructor(props) {
    super(props);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove = event => {
    this.setState({ x: event.clientX, y: event.clientY });
  };

  render() {
    return (
      
{this.props.render(this.state)}
); } } function MyComponent() { return ( (

The mouse position is ({x}, {y})

)} /> ); }

این قابلیت به راحتی برای برنامه‌های بین‌المللی‌سازی شده قابل انطباق است. به عنوان مثال، یک برنامه نقاشی را تصور کنید که توسط هنرمندان در ژاپن استفاده می‌شود. مختصات ماوس می‌تواند برای کنترل حرکت قلم‌مو استفاده شود:


 (
    
  )}
/>

۲. دریافت داده از API‌ها

دریافت داده از API‌ها یک کار رایج در توسعه وب است. یک کامپوننت Render Prop می‌تواند منطق دریافت داده را مدیریت کرده و داده‌ها را به فرزندان خود ارائه دهد.


class APIFetcher extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null, loading: true, error: null };
  }

  async componentDidMount() {
    try {
      const response = await fetch(this.props.url);
      const data = await response.json();
      this.setState({ data: data, loading: false });
    } catch (error) {
      this.setState({ error: error, loading: false });
    }
  }

  render() {
    return this.props.render(this.state);
  }
}

function MyComponent() {
  return (
     {
        if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; return
{JSON.stringify(data, null, 2)}
; }} /> ); }

این امر به ویژه هنگام کار با داده‌های محلی‌سازی شده مفید است. به عنوان مثال، نمایش نرخ ارز برای کاربران در مناطق مختلف را تصور کنید:


 {
    if (loading) return 

Loading exchange rates...

; if (error) return

Error fetching exchange rates.

; return (
    {Object.entries(data.rates).map(([currency, rate]) => (
  • {currency}: {rate}
  • ))}
); }} />

۳. مدیریت فرم

مدیریت وضعیت و اعتبارسنجی فرم می‌تواند پیچیده باشد. یک کامپوننت Render Prop می‌تواند منطق فرم را کپسوله کرده و وضعیت فرم و هندلرها را به فرزندان خود ارائه دهد.


class FormHandler extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: '', error: null };
  }

  handleChange = event => {
    this.setState({ value: event.target.value });
  };

  handleSubmit = event => {
    event.preventDefault();
    if (this.state.value.length < 5) {
      this.setState({ error: 'Value must be at least 5 characters long.' });
      return;
    }
    this.setState({ error: null });
    this.props.onSubmit(this.state.value);
  };

  render() {
    return this.props.render({
      value: this.state.value,
      handleChange: this.handleChange,
      handleSubmit: this.handleSubmit,
      error: this.state.error
    });
  }
}

function MyComponent() {
  return (
     alert(`Submitted value: ${value}`)}
      render={({ value, handleChange, handleSubmit, error }) => (
        
{error &&

{error}

}
)} /> ); }

تطبیق قوانین اعتبارسنجی فرم برای سازگاری با فرمت‌های آدرس بین‌المللی را در نظر بگیرید. کامپوننت FormHandler می‌تواند عمومی باقی بماند، در حالی که render prop منطق اعتبارسنجی و UI خاص برای مناطق مختلف را تعریف می‌کند:


 sendAddressToServer(address)}
  render={({ value, handleChange, handleSubmit, error }) => (
    
{/* Fields for address, adapting to regional formats */} {error &&

{error}

}
)} />

۴. Feature Flags و تست A/B

Render Props همچنین می‌تواند برای مدیریت feature flags و انجام تست‌های A/B استفاده شود. یک کامپوننت Render Prop می‌تواند تعیین کند که کدام نسخه از یک ویژگی بر اساس کاربر فعلی یا یک پرچم تولید شده به صورت تصادفی رندر شود.


class FeatureFlag extends React.Component {
  constructor(props) {
    super(props);
    this.state = { enabled: Math.random() < this.props.probability };
  }

  render() {
    return this.props.render(this.state.enabled);
  }
}

function MyComponent() {
  return (
     {
        if (enabled) {
          return 

New Feature!

; } else { return

Old Feature

; } }} /> ); }

هنگام انجام تست A/B برای مخاطبان جهانی، مهم است که کاربران را بر اساس زبان، منطقه یا سایر داده‌های دموگرافیک تقسیم‌بندی کنید. کامپوننت FeatureFlag می‌تواند برای در نظر گرفتن این عوامل هنگام تعیین اینکه کدام نسخه از یک ویژگی نمایش داده شود، اصلاح شود:


 {
    return isEnabled ?  : ;
  }}
/>

جایگزین‌های Render Props: کامپوننت‌های مرتبه بالاتر (HOCs) و Hooks

در حالی که Render Props یک الگوی قدرتمند است، رویکردهای جایگزینی وجود دارد که می‌توانند نتایج مشابهی را به دست آورند. دو جایگزین محبوب، کامپوننت‌های مرتبه بالاتر (HOCs) و Hooks هستند.

کامپوننت‌های مرتبه بالاتر (HOCs)

یک کامپوننت مرتبه بالاتر (HOC) تابعی است که یک کامپوننت را به عنوان آرگومان می‌گیرد و یک کامپوننت جدید و بهبود یافته را برمی‌گرداند. HOCها معمولاً برای افزودن عملکرد یا منطق به کامپوننت‌های موجود استفاده می‌شوند.

به عنوان مثال، HOC withMouse می‌تواند عملکرد ردیابی ماوس را به یک کامپوننت ارائه دهد:


function withMouse(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = { x: 0, y: 0 };
    }

    handleMouseMove = event => {
      this.setState({ x: event.clientX, y: event.clientY });
    };

    render() {
      return (
        
); } }; } function MyComponent(props) { return (

The mouse position is ({props.mouse.x}, {props.mouse.y})

); } const EnhancedComponent = withMouse(MyComponent);

در حالی که HOCها استفاده مجدد از کد را ارائه می‌دهند، می‌توانند منجر به تداخل نام propها شوند و ترکیب‌بندی کامپوننت‌ها را دشوارتر کنند، پدیده‌ای که به عنوان "جهنم wrapper" شناخته می‌شود.

Hooks

هوک‌های React که در React 16.8 معرفی شدند، روشی مستقیم‌تر و گویاتر برای استفاده مجدد از منطق حالت‌دار بین کامپوننت‌ها ارائه می‌دهند. هوک‌ها به شما امکان می‌دهند از کامپوننت‌های تابعی به وضعیت و ویژگی‌های چرخه حیات React "قلاب" بزنید.

با استفاده از هوک useMousePosition، عملکرد ردیابی ماوس را می‌توان به صورت زیر پیاده‌سازی کرد:


import { useState, useEffect } from 'react';

function useMousePosition() {
  const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    function handleMouseMove(event) {
      setMousePosition({ x: event.clientX, y: event.clientY });
    }

    window.addEventListener('mousemove', handleMouseMove);

    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
    };
  }, []);

  return mousePosition;
}

function MyComponent() {
  const mousePosition = useMousePosition();
  return (
    

The mouse position is ({mousePosition.x}, {mousePosition.y})

); }

هوک‌ها در مقایسه با Render Props و HOCها، روشی تمیزتر و مختصرتر برای استفاده مجدد از منطق حالت‌دار ارائه می‌دهند. آنها همچنین خوانایی و قابلیت نگهداری کد را بهبود می‌بخشند.

Render Props در مقابل Hooks: انتخاب ابزار مناسب

تصمیم‌گیری بین Render Props و Hooks به نیازمندی‌های خاص پروژه شما و ترجیحات شخصی شما بستگی دارد. در اینجا خلاصه‌ای از تفاوت‌های کلیدی آنها آورده شده است:

بهترین شیوه‌ها برای استفاده از Render Props

برای استفاده مؤثر از الگوی Render Props، بهترین شیوه‌های زیر را در نظر بگیرید:

نتیجه‌گیری

الگوی Render Props یک تکنیک ارزشمند برای ساخت کامپوننت‌های React انعطاف‌پذیر و قابل استفاده مجدد است. با کپسوله کردن منطق و ارائه آن به کامپوننت‌ها از طریق یک render prop، می‌توانید استفاده مجدد از کد، ترکیب‌بندی کامپوننت و جداسازی دغدغه‌ها را ترویج دهید. در حالی که هوک‌ها جایگزین مدرن‌تر و اغلب ساده‌تری را ارائه می‌دهند، Render Props همچنان یک ابزار قدرتمند در زرادخانه توسعه‌دهندگان React باقی می‌ماند، به ویژه هنگام کار با کدهای قدیمی یا سناریوهایی که نیاز به کنترل دقیق بر فرآیند رندرینگ دارند.

با درک مزایا و بهترین شیوه‌های الگوی Render Props، می‌توانید برنامه‌های قوی و سازگاری بسازید که به مخاطبان متنوع جهانی پاسخ می‌دهند و تجربه کاربری ثابت و جذابی را در مناطق و فرهنگ‌های مختلف تضمین می‌کنند. نکته کلیدی این است که الگوی مناسب – Render Props، HOCs یا Hooks – را بر اساس نیازهای خاص پروژه و تخصص تیم خود انتخاب کنید. به یاد داشته باشید که همیشه خوانایی، قابلیت نگهداری و عملکرد کد را هنگام تصمیم‌گیری‌های معماری در اولویت قرار دهید.